﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using IM.Interfaces;
using IM.Interfaces.Protocols;
using System.Threading;
using IM.DataTypes;

namespace IM.GUI.ContactList
{
    public partial class ContactList : UserControl
    {
        List<String> addedAccounts = new List<string>();
        int itemHeight = 0;

        int xOffset = 10;
        int yOffset = 10;

        SynchronizationContext uiContext;

        bool lockFocusChange = false;

        private bool showOnlyOnlineContacts = false;

        public bool ShowOnlyOnlineContacts
        {
            get { return this.showOnlyOnlineContacts; }
            set
            {
                this.showOnlyOnlineContacts = value;

                foreach (Control c in this.Controls)
                {
                    if (c is ContactListItem)
                    {
                        ContactListItem cl = c as ContactListItem;
                        cl.AllowHidingOfflineContacts = value;
                    }
                }

                this.Invalidate();
            }
        }

        public ContactList()
        {
            uiContext = WindowsFormsSynchronizationContext.Current;

            InitializeComponent();

            ShowOnlyOnlineContacts = false;

            Console.WriteLine("Creating contact list!");
        }

        protected override void InitLayout()
        {
            base.InitLayout();

            this.vScrollBar1.Enabled = true;
            this.vScrollBar1.Value = 0;
            this.vScrollBar1.Visible = true;
            this.vScrollBar1.Minimum = 0;
            this.vScrollBar1.LargeChange = 1;
            this.vScrollBar1.SmallChange = 1;
            this.vScrollBar1.Scroll += new ScrollEventHandler(vScrollBar1_Scroll);

            this.MouseWheel += new MouseEventHandler(ContactList_MouseWheel);
            this.MouseEnter += new EventHandler(ContactList_MouseEnter);
            this.MouseLeave += new EventHandler(ContactList_MouseLeave);
            this.LostFocus += new EventHandler(ContactList_LostFocus);
        }

        void ContactList_LostFocus(object sender, EventArgs e)
        {
            this.lockFocusChange = true;
        }

        void ContactList_MouseLeave(object sender, EventArgs e)
        {
            this.lockFocusChange = false;
        }

        void ContactList_MouseEnter(object sender, EventArgs e)
        {
            if (!this.lockFocusChange)
                this.Focus();
        }

        private void ContactList_MouseWheel(object sender, MouseEventArgs e)
        {
            int delta = -(e.Delta / 30);

            if (this.vScrollBar1.Value + delta < 0)
                this.vScrollBar1.Value = 0;

            else if (this.vScrollBar1.Value + delta > this.vScrollBar1.Maximum)
                this.vScrollBar1.Value = this.vScrollBar1.Maximum;

            else this.vScrollBar1.Value += delta;

            Invalidate();

        }

        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            Invalidate();
            Application.DoEvents();
        }

        public ContactList(IContainer container)
            : this()
        {
            container.Add(this);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
            e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;

            base.OnPaint(e);
            UpdateScrollBars();
        }
        
        private void UpdateScrollBars()
        {
            int i = 0;
            foreach (Control c in this.Controls)
            {
                if (c is ContactListItem)
                {
                    if (c.Visible || !this.ShowOnlyOnlineContacts)
                    {
                        c.Location = new Point(xOffset, (i - this.vScrollBar1.Value) * c.Height + yOffset);
                        i++;
                    }

                    itemHeight = c.Height;
                }
            }

            if (this.itemHeight != 0)
            {
                int visibleItemCount = ((this.Size.Height) / this.itemHeight);

                if (visibleItemCount <= i)
                {
                    this.vScrollBar1.Visible = true;
                    this.vScrollBar1.Maximum = i - visibleItemCount;
                }
                else
                {
                    this.vScrollBar1.Visible = false;
                    this.vScrollBar1.Maximum = 0;
                }
            }
        }

        private void RemoveContact(String accountname)
        {
            List<Control> controlsToRemove = new List<Control>();
            foreach (Control c in this.Controls)
            {
                if (c.Name.StartsWith(accountname))
                    controlsToRemove.Add(c);
            }

            foreach (var c in controlsToRemove)
                this.Controls.Remove(c);
        }

        public void UpdateContacts(User[] users)
        {
            uiContext.Send(new SendOrPostCallback(delegate(object state)
            {
                if (users.Length < 1)
                    return;

                if (!addedAccounts.Contains(users[0].Protocol.AccountName))
                    addedAccounts.Add(users[0].Protocol.AccountName);
                else
                {
                    RemoveContact(users[0].Protocol.AccountName);
                }

                foreach (var user in users)
                {
                    Control c = new ContactListItem() { AllowHidingOfflineContacts = this.ShowOnlyOnlineContacts, User = user, Name = String.Format("{0}-{1}", user.Protocol.AccountName, user.Username), Height = 40, Width = this.Width - this.vScrollBar1.Width - this.xOffset, Dock = DockStyle.None };
                    this.Controls.Add(c);
                }

                this.Invalidate();

            }), null);
        }
    }
}
